package com.cskaoyan.wordmemorize.task;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cskaoyan.wordmemorize.common.util.DateUtil;
import com.cskaoyan.wordmemorize.dao.entity.*;
import com.cskaoyan.wordmemorize.dao.mapper.*;
import com.cskaoyan.wordmemorize.service.UserService;
import com.cskaoyan.wordmemorize.sms.SmsDelayMessage;
import com.cskaoyan.wordmemorize.sms.SmsSender;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.DelayQueue;
import java.util.stream.Collectors;

@Component
@EnableScheduling
@Slf4j
public class UserMessageRemindTask {

    @Value("${user.remind.days}")
    Integer days;


    /**
     * 1. 加@Scheduled注解的方法，就代表定时任
     * 2. 通过cron属性指定定时任务执行时机
     */
    @Autowired
    UserMapper userMapper;

    @Autowired
    UserRemindMapper userRemindMapper;

    @Autowired
    UserRevStatisticsMapper userRevStatisticsMapper;

    @Autowired
    UserCheckinMapper userCheckinMapper;
    @Resource
    UserCheckinStatisticsMapper userCheckinStatisticsMapper;
    @Resource
    UserRemindMessageMapper userRemindMessageMapper;
    @Resource
    DelayQueue<SmsDelayMessage> delayQueue;

    // 消息发送工具类对象
    @Resource
    SmsSender smsSender;

    //    @Scheduled(cron = "0 0 0/1 * * ?")
    @Scheduled(cron = "30 25 0/1 * * ?")
    public void myTask() {


    //   LocalDateTime now = LocalDateTime.now();
        LocalTime currentTime = LocalTime.now();// 提取时间部分（HH:mm）
        LocalTime oneHourLater = currentTime.plusHours(1);


        LambdaQueryWrapper<UserRemindDO> queryWrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<UserRemindDO> fristNeedNotifyQueryWrapper =
                queryWrapper.between(UserRemindDO::getRemindTime, currentTime, oneHourLater);
        List<UserRemindDO> userRemindDOS = userRemindMapper.selectList(fristNeedNotifyQueryWrapper);
        List<UserRemindDO> collect = userRemindDOS.stream()
                .filter(userRemindDO -> needRemind(userRemindDO)).toList();


        if (collect.isEmpty()) {
            //System.out.println("List<UserRemindDO> :" + collect);
            return;
        }
        System.out.println("List<UserRemindDO> :" + collect);

        // 生成短信并放入延迟队列
        for (UserRemindDO user : collect) {
            Long userId = user.getUserId();
            LambdaQueryWrapper<UserDO> userDOLambdaQueryWrapper = new LambdaQueryWrapper<>();
            userDOLambdaQueryWrapper.eq(UserDO::getId, userId);
            UserDO userDO = userMapper.selectOne(userDOLambdaQueryWrapper);
            if (userDO == null) {
                continue;
            }
            Integer vocCountOfDay = userDO.getVocCountOfDay();

            LambdaQueryWrapper<UserRevStatisticsDO> lambdaQueryWrapper =
                    new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(UserRevStatisticsDO::getUserId, userId);
            UserRevStatisticsDO userRevStatisticsDO = userRevStatisticsMapper.selectOne(lambdaQueryWrapper);
            Integer vocCount = 0;
            if (userRevStatisticsDO != null) {
                vocCount = userRevStatisticsDO.getTotalCount();
            }

            Integer reqVocCount = vocCountOfDay - vocCount;
            if (reqVocCount < 0) {
                reqVocCount = 0;
            }


            //用户改变提醒时间且已在消息队列中(去重)
            delayQueue.removeIf(message -> userId.equals(message.getUserId()));
            SmsDelayMessage smsDelayMessage = new SmsDelayMessage(
                    userId, reqVocCount, user.getRemindTime(), userDO.getNickName(), userDO.getPhoneNumber().substring(4));
            System.out.println(smsDelayMessage);
            delayQueue.put(smsDelayMessage);
        }


    }

    /**
     * 这里@PstConstruct注解的作用为，让Spring在创建完对象后，自动调用该方法
     * 来完成对象的初始化(也就是说该方法会被Spring自动调用)
     */
    @PostConstruct
    public void init() {
        System.out.println("start to message remind....");

        new Thread(() -> {
            System.out.println("线程启动：开始处理延迟短信消息");
            while (true) {
                try {
                    System.out.println("准备从延迟队列中获取消息...");
                    SmsDelayMessage smsDelayMessage = delayQueue.take();
                    System.out.println("获取到短信延迟消息: " + smsDelayMessage);
                    // 发送短信
                    smsSender.sendRemindMessage(smsDelayMessage.getUserName(), smsDelayMessage.getVocCount(), smsDelayMessage.getPhoneNumber());
                    // 在数据库添加消息发送记录
                    UserRemindMessageDO userRemindMessageDO = new UserRemindMessageDO();
                    userRemindMessageDO.setUserId(smsDelayMessage.getUserId());
                    userRemindMessageDO.setPhoneNumber("+86-"+smsDelayMessage.getPhoneNumber());
                    userRemindMessageDO.setSendDate(LocalDate.now());
                    userRemindMessageMapper.insert(userRemindMessageDO);
                } catch (InterruptedException e) {
                    System.err.println("线程被中断");
                    e.printStackTrace();
                    Thread.currentThread().interrupt(); // 重置中断状态
                    break; // 退出循环
                } catch (Exception e) {
                    System.err.println("处理短信延迟消息时发生异常");
                    e.printStackTrace();
                }
            }
        }).start();


        log.info("end message remind....");


    }

    public boolean needRemind(UserRemindDO userRemindDO) {
        LambdaQueryWrapper<UserCheckinDO> hasCheckinWrapper = new LambdaQueryWrapper<>();
        hasCheckinWrapper.eq(UserCheckinDO::getSignDate, LocalDate.now())
                .eq(UserCheckinDO::getUserId, userRemindDO.getUserId());
        UserCheckinDO userCheckinDO = userCheckinMapper.selectOne(hasCheckinWrapper);
        if (userCheckinDO != null) {
            // 判断用户今天有签到,不必发送短信
            System.out.println("用户今天签到信息 userCheckinDO = " + userCheckinDO);
            return false;
        }
        System.out.println("用户今天签到信息 userCheckinDO = " + userCheckinDO);
        LambdaQueryWrapper<UserCheckinStatisticsDO> checkinStatisticsWrapper = new LambdaQueryWrapper<>();
        checkinStatisticsWrapper.eq(UserCheckinStatisticsDO::getUserId, userRemindDO.getUserId());
        UserCheckinStatisticsDO userCheckinStatisticsDO =
                userCheckinStatisticsMapper.selectOne(checkinStatisticsWrapper);

        if (userCheckinStatisticsDO == null || userCheckinStatisticsDO.getCurContinuousDays() < days) {
            // 用户最近连续签到天数小于指定天数
            System.out.println("用户最近连续签到天数 = " + userCheckinStatisticsDO.getCurContinuousDays());
            return false;
        }
        System.out.println("用户最近连续签到天数 = " + userCheckinStatisticsDO.getCurContinuousDays());
        LambdaQueryWrapper<UserRemindMessageDO> userRemindMessageWrapper = new LambdaQueryWrapper<>();
        userRemindMessageWrapper.eq(UserRemindMessageDO::getUserId, userRemindDO.getUserId()).orderByDesc(UserRemindMessageDO::getSendDate);
        List<UserRemindMessageDO> userRemindMessageDOS =
                userRemindMessageMapper.selectList(userRemindMessageWrapper);
        if (userRemindMessageDOS == null || userRemindMessageDOS.isEmpty()) {
            // 该用户最近一周内没有发过提醒短信
            return true;
        }
        System.out.println("userRemindMessageDOS = ");
        UserRemindMessageDO userRemindMessageDO = userRemindMessageDOS.get(0);
        long between = ChronoUnit.DAYS.between(LocalDate.now(), userRemindMessageDO.getSendDate());
        if (between < 7) {
            return false;
        }
        return true;


    }
}
